package com.rlevin.java.chmod;

/**
 * Adapted from Agile Java - Jeff Langr, Prentice Hall, ISBN: 0-13-148239-4
 * I've adapted it to an internal chmod-like system. @see Ugo
 * 
 * @author Jeff Langr (see above credit)
 * @author Rob Levin
 * @see Ugo
 */
public class Permissions {
	public static final String kOff = "Off";
	public static final String kExecute = "Execute"; 
	public static final String kWrite = "Write";
	public static final String kWriteExecute = "Write, Execute";
	public static final String kRead = "Read";
	public static final String kReadExecute = "Read, Execute";
	public static final String kReadWrite = "Read, Write";
	public static final String kReadWriteExecute = "Read, Write, Execute";
	public static final int ZERO=0x0;
	public static final int ONE=0x1;
	public static final int TWO=0x2;
	public static final int THREE=0x3;
	public static final int FOUR=0x4;
	public static final int FIVE=0x5;
	public static final int SIX=0X6;
	public static final int SEVEN=0x7;
	
	public enum PermissionLevel {
		OFF					(ZERO,kOff),
		EXECUTE				(ONE,kExecute),
		WRITE				(TWO,kWrite),
		WRITE_EXECUTE		(THREE,kWriteExecute),
		READ				(FOUR,kRead),
		READ_EXECUTE		(FIVE,kReadExecute),
		READ_WRITE			(SIX,kReadWrite),
		READ_WRITE_EXECUTE	(SEVEN,kReadWriteExecute);
		
		private int level;
		private String permLevelString;
		private PermissionLevel(int level, String perms) {
			this.level 	 = level;
			this.permLevelString = perms;
		}
		
		public String toString () {
			return this.permLevelString;
		}
		
		public int getLevel() {
			return this.level;
		}
	}
	
	public Permissions() {}
	

	// Thanks to Jeff Langr for this section of code ;)
	// ----------------------------- //
	public Permissions (Flag...flags) {
		for(Flag flag: flags)
			permissionSettings |= flag.mask;
	}
	
	public enum Flag {
		EXECUTE(1),
		WRITE(2),
		READ(4);
		
		private int mask;
		Flag(int mask) {
			this.mask = mask;
		}
	}
	
	private int permissionSettings = 0x0;	
	
	public void set(Flag...flags) {
		for(Flag flag: flags)
			permissionSettings |= flag.mask;
	}
	
	public void unset(Flag...flags) {
		for(Flag flag: flags) 
			permissionSettings &= ~flag.mask;
	}
	
	public boolean isOn(Flag flag) {
		return (permissionSettings & flag.mask) == flag.mask;		
	}
	
	public boolean isOff(Flag flag) {
		return !isOn(flag);
	}
	// ----------------------------- //

	
	public int getPermissionsLevelAsInt() {
		return this.permissionSettings;
	}
	
	public String getCurrentPermissionLevelAsString() {
		return getAPermissionLevelByInt(permissionSettings).toString();
	}
	
	public static PermissionLevel getAPermissionLevelByInt(final int permsInt) {
		switch (permsInt) {
			case ZERO:
				return Permissions.PermissionLevel.OFF;
			case ONE:
				return PermissionLevel.EXECUTE;
			case TWO:
				return PermissionLevel.WRITE;
			case THREE:
				return PermissionLevel.WRITE_EXECUTE;
			case FOUR:
				return PermissionLevel.READ;
			case FIVE:
				return PermissionLevel.READ_EXECUTE;
			case SIX:
				return PermissionLevel.READ_WRITE;
			case SEVEN:
				return PermissionLevel.READ_WRITE_EXECUTE;
			default:
				break;
		}
		return null;
	}
	
	public static Permissions createAPermissionByInt(int iLevel) {
		switch(iLevel) {
			case ZERO:
				return new Permissions();
			case ONE:
				return new Permissions(Permissions.Flag.EXECUTE);
			case TWO:
				return new Permissions(Permissions.Flag.WRITE);
			case THREE:
				return new Permissions(Permissions.Flag.WRITE, Permissions.Flag.EXECUTE);
			case FOUR:
				return new Permissions(Permissions.Flag.READ);
			case FIVE:
				return new Permissions(Permissions.Flag.READ, Permissions.Flag.EXECUTE);
			case SIX:
				return new Permissions(Permissions.Flag.READ, Permissions.Flag.WRITE);
			case SEVEN:
				return new Permissions(
						Permissions.Flag.READ, Permissions.Flag.WRITE, Permissions.Flag.EXECUTE);
			default:
				break;
		}
		return null;
	}
}
